package com.cal.utms.dao.maintenance;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;

import com.cal.utms.entity.CustodianContactPerson;
import com.cal.utms.entity.DealType;
import com.cal.utms.entity.Fund;
import com.cal.utms.entity.FundInstrumentMap;
import com.cal.utms.entity.InstrumentType;
import com.cal.utms.util.HibernateUtil;

public class NewFundDao {

	public Object add(Fund fund) {
		Object obj;
		Session session = HibernateUtil.getSession().openSession();
		Transaction tx = null;
		System.out.println("Saving new fund");
		try {
			tx = session.beginTransaction();
			obj = session.save(fund);

			for (CustodianContactPerson ccp : fund.getCustodianContactPersons()) {
				session.save(ccp);
			}
			System.out.println("Custodian contact persons Saved: " + fund.getFundName());

			for (FundInstrumentMap fim : fund.getFundInstrumentMaps()) {
				session.save(fim);
			}
			System.out.println("Fund Issuers Saved: " + fund.getFundName());
			tx.commit();
			System.out.println("Fund Added: " + fund.getFundName());
		} catch (Exception ex) {
			tx.rollback();
			obj = new Object();
			System.out.println("Exception in save Fund " + fund.getFundName() + " : " + ex.getMessage());
			ex.printStackTrace();
		} finally {
			session.close();
		}
		return obj;
	}

	public void update(Fund fund) {
		System.out.println("Updating the fund");
		Session session = HibernateUtil.getSession().openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			session.update(fund);
			tx.commit();
			System.out.println("Fund updated");
		} catch (Exception ex) {
			tx.rollback();
			System.out.println("Exception in Updating the Fund. ID: " + fund.getId() + " : " + ex.getMessage());
			ex.printStackTrace();
		} finally {
			session.close();
		}
	}

	public Fund getById(Integer id) {
		Session session = HibernateUtil.getSession().openSession();
		Fund fund = null;
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			fund = (Fund) session.get(Fund.class, id);
			tx.commit();
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			System.out.println("Exception getByID Fund " + e.getMessage());
		} finally {
			session.close();
		}
		return fund;
	}

	@SuppressWarnings("unchecked")
	public Fund getByCode(String code) {
		Session session = HibernateUtil.getSession().openSession();
		Fund fund = null;
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			Query query = session.createQuery("select c from Fund c where c.fundCode = :code");
			query.setParameter("code", code);
			List<Fund> li = query.list();
			if(li.size()>0){
				fund = li.get(0);
			}			
			tx.commit();
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			System.out.println("Exception getByID Fund " + e.getMessage());
			e.printStackTrace();
		} finally {
			session.close();
		}
		return fund;
	}

	// Query query =
	// session.createQuery("select c from CustodianContactPerson c where c.fund.id = :fundId");

	@SuppressWarnings("unchecked")
	public List<Fund> getNames() {
		Session session = HibernateUtil.getSession().openSession();
		Criteria cr = session.createCriteria(Fund.class);
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("id"), "id");
		projectionList.add(Projections.property("fundCode"), "fundCode");
		projectionList.add(Projections.property("fundName"), "fundName");
		projectionList.add(Projections.property("status"), "status");
		projectionList.add(Projections.property("updateDate"), "updateDate");
		cr.setProjection(projectionList);
		cr.setResultTransformer(Transformers.aliasToBean(Fund.class));
		List<Fund> list = cr.list();
		session.close();
		return list;
	}

	@SuppressWarnings("unchecked")
	public List<Fund> getNames(String query) {
		Session session = HibernateUtil.getSession().openSession();
		Criteria cr = session.createCriteria(Fund.class);
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("id"), "id");
		projectionList.add(Projections.property("fundCode"), "fundCode");
		projectionList.add(Projections.property("fundName"), "fundName");
		projectionList.add(Projections.property("status"), "status");
		projectionList.add(Projections.property("updateDate"), "updateDate");
		cr.setProjection(projectionList);
		cr.setResultTransformer(Transformers.aliasToBean(Fund.class));
		List<Fund> list = cr.list();
		session.close();
		List<Fund> res = new ArrayList<Fund>();
		for (Fund fund : list) {
			if (fund.getFundName().toUpperCase().startsWith(query.toUpperCase())) {
				res.add(fund);
			}
		}
		return res;
	}
	
	@SuppressWarnings("unchecked")
	public List<Fund> getNamesForEod() {
		Session session = HibernateUtil.getSession().openSession();
		Criteria cr = session.createCriteria(Fund.class);
		
		ProjectionList projectionList = Projections.projectionList();
		projectionList.add(Projections.property("id"), "id");
		projectionList.add(Projections.property("fundCode"), "fundCode");
		projectionList.add(Projections.property("fundName"), "fundName");
		projectionList.add(Projections.property("status"), "status");
		projectionList.add(Projections.property("updateDate"), "updateDate");
		projectionList.add(Projections.property("portfolio"), "portfolio");
		projectionList.add(Projections.property("unitValue"), "unitValue");
		cr.setProjection(projectionList);
		
		cr.add(Restrictions.eq("this.status", "Confirmed"));
		
		cr.setResultTransformer(Transformers.aliasToBean(Fund.class));
		List<Fund> list = cr.list();
		session.close();
		return list;
	}
	
	@SuppressWarnings("unchecked")
	public List<Fund> getNamesForDeal(String dealType, String instrumentType) {		
		int insTypeId = 0;
		Transaction tx = null;
		List<Fund> res = new ArrayList<Fund>();
		List<Fund> li = null;
		try{
			insTypeId = Integer.parseInt(instrumentType);
		}catch(NumberFormatException nfe){
			return res;
		}
		Session session = HibernateUtil.getSession().openSession();
		try {
			tx = session.beginTransaction();
			Query query = session.createQuery("select c from Fund c where c.status = :status");
			//Query query = session.createQuery("select c.fund from FundInstrumentMap c where c.fund.status=:status and c.dealTypeBean.code=:code and c.instrumentTypeId=:insType" );
			query.setParameter("status", "Confirmed");
			//query.setParameter("code", dealType);
			//query.setParameter("insType", insTypeId);
			li = query.list();
			tx.commit();			
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			System.out.println("Exception getFundForDeal dealType:"+dealType+" InsTypeId: "+instrumentType+" :"+ e.getMessage());
			e.printStackTrace();
		} finally {
			session.close();
		}
		for(Fund fund:li){
			for(FundInstrumentMap fim:fund.getFundInstrumentMaps()){
				if(fim.getDealTypeBean().getCode().equalsIgnoreCase(dealType)&&fim.getInstrumentTypeId()==insTypeId){
					Fund resFund = new Fund();
					resFund.setFundCode(fund.getFundCode());
					resFund.setFundName(fund.getFundName());
					resFund.setId(fund.getId());
					res.add(resFund);
					break;
				}
			}
			
		}
		return res;

	}	
	
	@SuppressWarnings("unchecked")
	public List<Fund> getNamesForDeal(String dealType) {
		Session session = HibernateUtil.getSession().openSession();
		Transaction tx = null;
		List<Fund> res = new ArrayList<Fund>();
		try {
			tx = session.beginTransaction();
			Query query = session.createQuery("select c from Fund c where c.status = :status");
			query.setParameter("status", "Confirmed");
			List<Fund> li = query.list();
			tx.commit();
			Fund tempFund = null;
			
			for(Fund fund:li){
				for(DealType dlType:fund.getDealTypes()){
					if(dlType.getCode().equalsIgnoreCase(dealType)){
						//res.add(fund);
						tempFund = new Fund();
						tempFund.setId(fund.getId());
						tempFund.setFundCode(fund.getFundCode());
						tempFund.setFundName(fund.getFundName());
						res.add(tempFund);
						break;
					}
				}				
			}
			
		} catch (Exception e) {
			if (tx != null)
				tx.rollback();
			System.out.println("Exception getFundForDeal dealType:"+dealType+" :"+ e.getMessage());
			e.printStackTrace();
		} finally {
			session.close();
		}
		return res;

	}

	public static void main(String[] args) {
		Session session = HibernateUtil.getSession().openSession();

		/*
		 * Criteria cr = session.createCriteria(Fund.class)
		 * .setProjection(Projections.projectionList()
		 * .add(Projections.property("id"), "id")
		 * .add(Projections.property("fundCode"), "fundCode")
		 * .add(Projections.property("fundName"), "fundName"))
		 * .setResultTransformer(Transformers.aliasToBean(Fund.class));
		 * 
		 * @SuppressWarnings("unchecked") List<Fund> list = cr.list(); for(Fund
		 * fund:list){
		 * System.out.println(fund.getId()+" : "+fund.getFundCode()+" : "
		 * +fund.getFundName()); }
		 */

		NewFundDao nfd = new NewFundDao();

		System.out.println("1");
		
		for(InstrumentType inTy: nfd.getInsTypesForDealType(18, "PURCH")){
			System.out.println(inTy.getInstrumentName());
		}
		System.out.println("4");

		session.close();
	}

	@SuppressWarnings("unchecked")
	public List<Fund> getFundWithUnitValue() {
		Session session = HibernateUtil.getSession().openSession();
		Transaction transaction = null;
		List<Fund> funds = new ArrayList<Fund>();
		try {
			transaction = session.beginTransaction();
			funds = session.createQuery("From Fund F").list();
			transaction.commit();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return funds;
	}
	
	
	@SuppressWarnings("unchecked")
	public List<InstrumentType> getInsTypesForDealType(int fundId, String dealType) {
		List<InstrumentType> insTypes = new ArrayList<InstrumentType>();
		Fund fund = null;
		List<Integer> insIds = new ArrayList<Integer>();
		Session session = null;
		
		fund = this.getById(fundId);
		for(FundInstrumentMap fim: fund.getFundInstrumentMaps()){
			if(fim.getDealTypeBean().getCode().equals(dealType))
				insIds.add(fim.getInstrumentTypeId());
		}		
		try{
			session = HibernateUtil.getSession().openSession();
			Transaction tx = session.beginTransaction();
			Query query = session.createQuery("select c from InstrumentType c where c.id in (:insIds)");
			query.setParameterList("insIds", insIds);
			insTypes = query.list();
			tx.commit();
		}catch(HibernateException he){
			System.out.println("Hibernate Exception : "+ he.getLocalizedMessage());
			return insTypes;
		}finally{
			if(session!=null){
				try{
					session.close();
				}catch(HibernateException e){
					e.printStackTrace();
				}				
			}
								
		}
		return insTypes;
	}

	
	
	

}
